package com.zzzy.server.config;

import com.zzzy.framework.common.constant.TokenNameConstant;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.apache.commons.lang3.StringUtils;
import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Comparator;
import java.util.stream.Collectors;


/**
 * Description: Swagger 自动配置类，基于 OpenAPI + Springdoc 实现。
 *
 * @author fc
 * @date 2024/4/9
 */
@Configuration
@ConditionalOnProperty(name = "springdoc.api-docs.enabled", havingValue = "true", matchIfMissing = false)
public class SwaggerConfig {

    @Bean
    public OpenAPI api() {
        return new OpenAPI().info(new Info().title("合同管理系统")
                .description("分组为系统功能接口、全部接口")
                .version("v1.0.0"))
                // 配置全局鉴权参数-Authorize
                .components(new Components()
                        .addSecuritySchemes(TokenNameConstant.TOKEN,
                                new SecurityScheme()
                                        .name(TokenNameConstant.TOKEN)
                                        .type(SecurityScheme.Type.APIKEY)
                                        .in(SecurityScheme.In.HEADER)
                        )
                );
    }
    @Bean()
    public GroupedOpenApi allApi() {
        return GroupedOpenApi.builder()
                .group("全部接口")
                .pathsToMatch("/**")
                .addOpenApiCustomiser(sortTagsAlphabetically())
                .build();
    }

    @Bean()
    public GroupedOpenApi serverApi() {
        return GroupedOpenApi.builder()
                .group("公共服务(登录等)")
                .pathsToMatch("/**")
                .packagesToScan("com.zzzy.server.controller")
                .addOpenApiCustomiser(sortTagsAlphabetically())
                .build();
    }
    @Bean
    public GroupedOpenApi systemApi() {
        return GroupedOpenApi.builder()
                .group("系统管理")
                .pathsToMatch("/**")
                .packagesToScan("com.zzzy.sys.controller")
                .addOpenApiCustomiser(sortTagsAlphabetically())
                .build();
    }
    @Bean
    public GroupedOpenApi contractApi() {
        return GroupedOpenApi.builder()
                .group("合同管理")
                .pathsToMatch("/**")
                .packagesToScan("com.zzzy.cont.controller")
                .addOpenApiCustomiser(sortTagsAlphabetically())
                .build();
    }
    @Bean
    public GroupedOpenApi documentApi() {
        return GroupedOpenApi.builder()
                .group("公文管理")
                .pathsToMatch("/**")
                .packagesToScan("com.zzzy.doc.controller")
                .addOpenApiCustomiser(sortTagsAlphabetically())
                .build();
    }

    public OpenApiCustomiser sortTagsAlphabetically() {
        return openApi -> openApi.setTags(openApi.getTags()
                .stream()
                .sorted(Comparator.comparing(tag -> StringUtils.stripAccents(tag.getDescription())))
                .collect(Collectors.toList()));
    }

    @Bean
    public GlobalOpenApiCustomizer globalOpenApiCustomizer() {
        return openApi -> {
            // 全局添加鉴权参数
            if (openApi.getPaths() != null) {
                openApi.getPaths().forEach((s, pathItem) -> {
                    // 登录接口/验证码不需要添加鉴权参数
                    if ("/login".equals(s) || "/getVerifyCode".equals(s)) {
                        return;
                    }
                    // 接口添加鉴权参数
                    pathItem.readOperations()
                            .forEach(operation ->
                                    operation.addSecurityItem(new SecurityRequirement().addList(TokenNameConstant.TOKEN))
                            );
                });
            }
        };
    }
}

